﻿using System;
using System.Drawing;
using System.Collections.Generic;
using Ants.SimpleDistributionProblem;
using Ants.SimpleDistributionProblem.DTO;
using DTO.DTOEventArgs;
using Model;

namespace Controller
{
    /// <summary>
    /// Class representing main controller.
    /// </summary>
    public class MainController
    {
        /// <summary>
        /// Occurs when progress of finding solution changes.
        /// </summary>
        public event EventHandler<ProgressChangedEventArgs> FindSolutionProgressChanged;

        /// <summary>
        /// Occurs when time left changes.
        /// </summary>
        public event EventHandler<TimeLeftChangedEventArgs> TimeLeftChanged;

        /// <summary>
        /// Finds the solution.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="properties">The properties.</param>
        /// <returns>The solution.</returns>
        public Solution FindSolution(Data data, AntAlgorithmProperties properties)
        {
            SimpleDistributionProblem ants = new SimpleDistributionProblem();
            ants.FindSolutionProgressChanged += this.FindSolutionProgressChanged;
            ants.TimeLeftChanged += this.TimeLeftChanged;
            return ants.FindSolution(data, properties);
        }

        /// <summary>
        /// Opens the file.
        /// </summary>
        /// <param name="path">The path.</param>
        /// <returns>The data.</returns>
        public Data OpenFile(string path)
        {
            return FileDataProvider.Instance.OpenFile(path);
        }

        /// <summary>
        /// Saves the data.
        /// </summary>
        /// <param name="solution">Solution to be saved.</param>
        /// <param name="data">Data needed to get city indices</param>
        public void SaveData(Solution solution, Data data) {
            Point startingPoint = data.Cities[0];
            Dictionary<Point, int> cityIndices = new Dictionary<Point,int>();
            List<Lap> laps = new List<Lap>();
            int routeNumber = 0;
            int cityIndex = 0;
            foreach (Point city in data.Cities) {
                cityIndices.Add(city, cityIndex);
                cityIndex++;
            }
            foreach (RoutePart route in solution.Route) {
                if (route.PointA == startingPoint) {
                    cityIndex = 0;
                    routeNumber++;
                    laps.Add(new Lap());
                    laps[routeNumber - 1].CityIndices.Add(0);
                    cityIndices.TryGetValue(route.PointB, out cityIndex);
                    laps[routeNumber - 1].CityIndices.Add(cityIndex);
                } else if (route.PointB == startingPoint) {
                    laps[routeNumber - 1].CityIndices.Add(0);
                } else { // route not connected with starting/ending point
                    cityIndices.TryGetValue(route.PointB, out cityIndex);
                    laps[routeNumber - 1].CityIndices.Add(cityIndex);
                }
            }
            FileDataProvider.Instance.SaveData(solution.Cost, routeNumber, laps);
        }
    }
}